package cn.nkpro.elcube.mq;

import cn.nkpro.elcube.cloud.CloudConstants;
import cn.nkpro.elcube.cloud.NkCloudMQManager;
import cn.nkpro.elcube.co.mq.NkMQManager;
import com.rabbitmq.http.client.Client;
import com.rabbitmq.http.client.GetAckMode;
import com.rabbitmq.http.client.GetEncoding;
import com.rabbitmq.http.client.domain.InboundMessage;
import com.rabbitmq.http.client.domain.QueueInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.SingletonBeanRegistry;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.List;

@Component
@ConditionalOnProperty("spring.rabbitmq.client.url")
public class NkMQManagerImpl implements NkMQManager, NkCloudMQManager, InitializingBean, BeanFactoryAware {


    @Value("${nk.cloud.id:}")
    private String cloudId;

    @Value("${spring.rabbitmq.client.url}")
    private String url;
    @Value("${spring.rabbitmq.client.username:admin}")
    private String username;
    @Value("${spring.rabbitmq.client.password:admin}")
    private String password;
    @Value("${spring.rabbitmq.virtual-host:}")
    private String virtualHost;

    @Autowired@SuppressWarnings("all")
    private RabbitTemplate rabbitTemplate;

    private Client client;
    private RabbitAdmin rabbitAdmin;
    private BeanFactory beanFactory;
    private DirectExchange exchange;
    private Queue queue;

    public List<InboundMessage> getMessages(String queue,int rows){
        return client.get(virtualHost, queue, rows, GetAckMode.NACK_REQUEUE_TRUE, GetEncoding.AUTO);
    }

    public List<QueueInfo> getQueues(){
        return client.getQueues(virtualHost);
    }

    @Override
    public void publish(String exchange, String queue, Serializable message){
        rabbitTemplate.convertAndSend(StringUtils.defaultString(exchange,rabbitTemplate.getExchange()),queue,message);
    }

    public void resume(String queue){
        rabbitTemplate.receiveAndReply(queue,(payload)-> payload,(msg, payload)->{
            String oExchange = msg.getMessageProperties().getHeader("x-first-death-exchange");
            String oQueue = msg.getMessageProperties().getHeader("x-first-death-queue");
            return new Address(oExchange,oQueue);
        });
    }

    public void discard(String queue){
        rabbitTemplate.receive(queue);
    }


    /**
     * 注入beanFactory
     */
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
    /**
     * 注册MQ资源
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        client = new Client(url,username,password);
        rabbitAdmin = new RabbitAdmin(rabbitTemplate.getConnectionFactory());

//        /*
//         * todo 绑定同步队列到交换机
//         * 这里需要调整成在UI中自定义
//         * 并清理不存在的绑定关系
//         */
//        if(StringUtils.isNotBlank(cloudGroup)){
//            cloudProperties.getSubscribes().forEach(type->{
//                Binding bindingCustom = BindingBuilder.bind(queue).to(exchange).with(type);
//                rabbitAdmin.declareBinding(bindingCustom);
//            });
//        }

        if(StringUtils.isNotBlank(cloudId)){

            SingletonBeanRegistry beanRegistry = (SingletonBeanRegistry) beanFactory;

            /*
             * 注册 云服务 交换机
             */
            exchange = new DirectExchange(CloudConstants.EXCHANGE_NAME);
            beanRegistry.registerSingleton("ELCubeCloudSyncExchange",exchange);

            String queueName     = CloudConstants.QUEUE_NAME+ cloudId;
            String queueNameDead = queueName+".dead";

            /*
             * 死信队列
             */
            Queue queueDead = new Queue(queueNameDead);
            beanRegistry.registerSingleton("ELCubeCloudSyncQueue"  +queueNameDead,queueDead);
            Binding bindingDead = BindingBuilder.bind(queueDead).to(exchange).withQueueName();
            beanRegistry.registerSingleton("ELCubeCloudSyncBinding"+queueNameDead,bindingDead);

            /*
             * 同步队列
             */
            queue = QueueBuilder.durable(queueName)
                    .deadLetterExchange(CloudConstants.EXCHANGE_NAME)
                    .deadLetterRoutingKey(queueNameDead)
                    .build();
            beanRegistry.registerSingleton("ELCubeCloudSyncQueue"  +queueName,queue);
            Binding binding = BindingBuilder.bind(queue).to(exchange).withQueueName();
            beanRegistry.registerSingleton("ELCubeCloudSyncBinding"+queueName,binding);
        }
    }


    @Override
    public void declareBinding(String bindingKey){
        Binding bindingCustom = BindingBuilder
                .bind(queue)
                .to(exchange)
                .with(bindingKey);
        rabbitAdmin.declareBinding(bindingCustom);
    }

    @Override
    public void removeBinding(String bindingKey){
        Binding bindingCustom = BindingBuilder
                .bind(queue)
                .to(exchange)
                .with(bindingKey);
        rabbitAdmin.removeBinding(bindingCustom);
    }

}
